from PySide6.QtCore import QObject, Signal, QThread
from bleak import BleakScanner, BleakClient
import asyncio
import time

class BluetoothDevice:
    """蓝牙设备信息封装类"""
    def __init__(self, address, name):
        self.address = address
        self.name = name or "未知设备"  # 如果设备没有名称，使用默认值
    
    def __str__(self):
        """用于在下拉框中显示设备信息"""
        return f"{self.name} ({self.address})"

class BluetoothManager(QObject):
    """蓝牙管理类，基于bleak库实现BLE设备扫描和通信"""
    # 信号定义
    devices_updated = Signal(list)  # 设备列表更新信号
    status_updated = Signal(str)    # 状态更新信号
    error_occurred = Signal(str)    # 错误信号
    data_received = Signal(bytes)   # 数据接收信号
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.scanning = False
        self.client = None
        self.connected_device = None
        self.scan_thread = None
    
    def start_scan(self):
        """开始扫描BLE设备"""
        if self.scanning:
            return
            
        self.scanning = True
        self.status_updated.emit("正在扫描BLE设备...")
        
        # 创建并启动扫描线程
        self.scan_thread = QThread()
        self.scan_worker = ScanWorker()
        self.scan_worker.moveToThread(self.scan_thread)
        
        # 连接信号
        self.scan_worker.finished.connect(self.on_scan_finished)
        self.scan_worker.devices_found.connect(self.process_scan_results)
        self.scan_worker.error_occurred.connect(self.error_occurred)
        self.scan_thread.started.connect(self.scan_worker.run)
        
        self.scan_thread.start()
    
    def process_scan_results(self, bleak_devices):
        """处理扫描结果，转换为自定义BluetoothDevice对象"""
        devices = []
        for d in bleak_devices:
            devices.append(BluetoothDevice(d.address, d.name))
        self.devices_updated.emit(devices)
    
    def on_scan_finished(self):
        """扫描完成回调"""
        self.scanning = False
        self.status_updated.emit("扫描完成")
        self.scan_thread.quit()
        self.scan_thread.wait()
    
    async def _connect(self, device_address):
        """异步连接设备"""
        try:
            self.client = BleakClient(device_address)
            self.status_updated.emit(f"正在连接 {device_address}...")
            
            if await self.client.connect():
                self.connected_device = device_address
                self.status_updated.emit(f"已连接到 {device_address}")
                return True
            else:
                self.error_occurred.emit(f"无法连接到 {device_address}")
                return False
        except Exception as e:
            self.error_occurred.emit(f"连接错误: {str(e)}")
            return False
    
    def connect_device(self, device):
        """连接选中的设备（供UI调用）"""
        if self.client and self.client.is_connected:
            self.error_occurred.emit("已连接到其他设备，请先断开")
            return
            
        # 在新线程中执行连接操作，避免阻塞UI
        self.connect_thread = QThread()
        self.connect_worker = ConnectWorker(device.address)
        self.connect_worker.moveToThread(self.connect_thread)
        
        self.connect_worker.result.connect(self.on_connect_result)
        self.connect_worker.error.connect(self.error_occurred)
        self.connect_thread.started.connect(self.connect_worker.run)
        
        self.connect_thread.start()
    
    def on_connect_result(self, success):
        """连接结果处理"""
        self.connect_thread.quit()
        self.connect_thread.wait()
    
    async def _disconnect(self):
        """异步断开连接"""
        if self.client and self.client.is_connected:
            await self.client.disconnect()
            self.connected_device = None
            self.status_updated.emit("已断开连接")
    
    def disconnect_device(self):
        """断开当前连接"""
        if not self.client or not self.client.is_connected:
            return
            
        self.disconnect_thread = QThread()
        self.disconnect_worker = DisconnectWorker(self.client)
        self.disconnect_worker.moveToThread(self.disconnect_thread)
        
        self.disconnect_worker.finished.connect(self.disconnect_thread.quit)
        self.disconnect_thread.started.connect(self.disconnect_worker.run)
        
        self.disconnect_thread.start()
    
    async def _send_data(self, data):
        """异步发送数据（需要指定正确的特征值UUID）"""
        if not self.client or not self.client.is_connected:
            self.error_occurred.emit("未连接到设备")
            return False
            
        try:
            # 注意：需要替换为目标设备的特征值UUID
            characteristic_uuid = "0000ffe1-0000-1000-8000-00805f9b34fb"
            await self.client.write_gatt_char(characteristic_uuid, data)
            return True
        except Exception as e:
            self.error_occurred.emit(f"发送数据失败: {str(e)}")
            return False
    
    def send_data(self, data):
        """发送数据（供UI调用）"""
        if not self.connected_device:
            self.error_occurred.emit("未连接到设备")
            return
            
        self.send_thread = QThread()
        self.send_worker = SendDataWorker(self.client, data)
        self.send_worker.moveToThread(self.send_thread)
        
        self.send_worker.result.connect(self.on_send_result)
        self.send_worker.error.connect(self.error_occurred)
        self.send_thread.started.connect(self.send_worker.run)
        
        self.send_thread.start()
    
    def on_send_result(self, success):
        """发送结果处理"""
        if success:
            self.status_updated.emit("数据发送成功")
        self.send_thread.quit()
        self.send_thread.wait()

# 扫描工作线程
class ScanWorker(QObject):
    finished = Signal()
    devices_found = Signal(list)
    error_occurred = Signal(str)
    
    async def _scan(self):
        """异步扫描设备"""
        try:
            devices = await BleakScanner.discover(timeout=4.0)
            self.devices_found.emit(devices)
        except Exception as e:
            self.error_occurred.emit(f"扫描错误: {str(e)}")
        finally:
            self.finished.emit()
    
    def run(self):
        """运行扫描任务"""
        asyncio.run(self._scan())

# 连接工作线程
class ConnectWorker(QObject):
    result = Signal(bool)
    error = Signal(str)
    
    def __init__(self, device_address):
        super().__init__()
        self.device_address = device_address
    
    async def _connect(self):
        """执行连接操作"""
        try:
            async with BleakClient(self.device_address) as client:
                if client.is_connected:
                    # 保持连接，这里可以添加特征值监听等逻辑
                    return True
            return False
        except Exception as e:
            self.error.emit(f"连接错误: {str(e)}")
            return False
    
    def run(self):
        """运行连接任务"""
        result = asyncio.run(self._connect())
        self.result.emit(result)

# 断开连接工作线程
class DisconnectWorker(QObject):
    finished = Signal()
    
    def __init__(self, client):
        super().__init__()
        self.client = client
    
    async def _disconnect(self):
        """执行断开连接操作"""
        if self.client.is_connected:
            await self.client.disconnect()
        self.finished.emit()
    
    def run(self):
        """运行断开连接任务"""
        asyncio.run(self._disconnect())

# 发送数据工作线程
class SendDataWorker(QObject):
    result = Signal(bool)
    error = Signal(str)
    
    def __init__(self, client, data):
        super().__init__()
        self.client = client
        self.data = data
    
    async def _send(self):
        """执行发送数据操作"""
        try:
            # 注意：替换为实际设备的特征值UUID
            characteristic_uuid = "0000ffe1-0000-1000-8000-00805f9b34fb"
            await self.client.write_gatt_char(characteristic_uuid, self.data)
            return True
        except Exception as e:
            self.error.emit(f"发送错误: {str(e)}")
            return False
    
    def run(self):
        """运行发送数据任务"""
        result = asyncio.run(self._send())
        self.result.emit(result)
    